<template>
  <div class="set-params" @click="($event) => $event.stopPropagation()">
    <div class="description">
      <!-- 联接子句 -->
      <div class="module-title">
        <span
          >联接子句:<span class="title-text"
            >（多个子句是"且"的关系）</span
          ></span
        >
      </div>
      <div class="join-clause">
        <div
          v-for="(clause, index) in joinClauseList"
          :key="index"
          class="clause-content"
        >
          <!-- 推荐的子句 -->
          <div class="clause-left">
            <a-select
              v-model="clause.leftHeaderName"
              :filter-option="filterOption"
              class="clause-conditions"
              placeholder="请选择列"
              size="small"
              show-search
              option-filter-prop="children"
              @change="(value) => valueChange(index, 'left', value)"
            >
              <!-- 节点data.input 中是输入表名及字段 [0] 左表 -->
              <a-select-option
                v-for="(column1, index) in leftColumns"
                :key="'column1' + index"
                :title="column1"
                :value="column1"
                >{{ column1 }}</a-select-option
              >
            </a-select>
            <a-select
              v-model="clause.operator"
              class="clause-symbol"
              size="small"
              @change="relationValueChange(index)"
            >
              <a-select-option value=">">&gt;</a-select-option>
              <a-select-option value="<">&lt;</a-select-option>
              <a-select-option value="=">=</a-select-option>
              <a-select-option value="!=">!=</a-select-option>
            </a-select>
            <a-select
              v-model="clause.rightHeaderName"
              :filter-option="filterOption"
              class="clause-conditions"
              placeholder="请选择列"
              size="small"
              show-search
              option-filter-prop="children"
              @change="(value) => valueChange(index, 'right', value)"
            >
              <!-- 节点data.input 中是输入表名及字段 [1] 右 -->
              <a-select-option
                v-for="(column2, index) in rightColumns"
                :key="'column2' + index"
                :title="column2"
                :value="column2"
                >{{ column2 }}</a-select-option
              >
            </a-select>
          </div>
          <!-- 移除指定 -->
          <a-tooltip :mouse-enter-delay="0.5" placement="top">
            <span slot="title">移除联接子句</span>
            <a-icon-font
              class="delete-clause-icon"
              type="iconjianshao"
              @click="removeClause(index)"
            />
          </a-tooltip>
          <!-- 数据预览  -->
          <popover-detail
            :score="clause.score"
            :header-score="clause.headerScore"
            :value-score="clause.valueScore"
            :current-clause="clause"
            :input="selectNode.data.input"
            :parent-id="selectNode.parentId"
            :task-id="selectNode.id"
            :left-color="leftColor"
            :right-color="rightColor"
            class="popover-detail"
          />
        </div>
        <div v-if="joinClauseList.length === 0" class="empty-join-clause">
          -- 请添加联接子句 --
        </div>
        <!-- 添加联接子句 -->
        <div class="add-clause">
          <a-icon-font type="icontianjiajiedian" @click="addClause" />
          <span slot="title" @click="addClause">添加联接子句</span>
        </div>
      </div>

      <!-- 联接类型 -->
      <div class="module-title">联接类型:</div>
      <div class="auto-join-model">
        <div class="join-node-name" align="right">
          {{ selectNode.data.input[0].nodeName }}
        </div>
        <!-- 韦恩图 -->
        <venn-of-join-type
          :join-type="joinType"
          :left-color="leftColor"
          :right-color="rightColor"
          :svg-height="110"
          :svg-width="130"
          @toggle="toggleJoin"
        />
        <div class="join-node-name">
          {{ selectNode.data.input[1] && selectNode.data.input[1].nodeName }}
        </div>
      </div>

      <!-- 结果概览 -->
      <div class="module-title">结果概览:<span class="title-text"></span></div>
      <div class="results-overview-content">
        <a-spin :spinning="resultLoading" tip="Loading..." :delay="100">
          <!--          -->
          <div
            v-if="showResultOverview"
            :style="{ height: '96px', width: '100%' }"
          >
            <result-overview
              :join-clause-list="joinClauseList"
              :join-type="joinType"
              :left-color="leftColor"
              :right-color="rightColor"
              :left-node-name="selectNode.data.input[0].nodeName"
              :right-node-name="selectNode.data.input[1].nodeName"
              :result="result"
            />
          </div>
          <div v-else class="empty-clause-result">
            <span>{{ resultWarning }}</span>
          </div>
        </a-spin>
      </div>

      <!-- 推荐连接子句 -->
      <div class="module-title">推荐联接子句:</div>
      <div class="auto-join-recommend">
        <div class="legend-color">
          <span class="header-score-legend">字段名推荐</span>
          <span class="value-score-legend">字段值推荐</span>
        </div>
        <div class="recommend-clause">
          <template v-for="(clause, index) in autoJoinRecommendation">
            <div
              v-if="index < 20 && isShow(clause.id)"
              :key="index"
              class="clause-item"
            >
              <!-- 推荐的字句 -->
              <div class="clause-text">
                <span
                  class="clause-field clause-field-left"
                  :style="{ color: leftColor }"
                  :title="clause.leftHeaderName"
                  >{{ clause.leftHeaderName }}</span
                >
                <span class="relation">=</span>
                <span
                  class="clause-field clause-field-right"
                  :style="{ color: rightColor }"
                  :title="clause.rightHeaderName"
                  >{{ clause.rightHeaderName }}</span
                >
              </div>
              <popover-coefficient-bar
                :score="clause.score"
                :header-score="clause.headerScore"
                :value-score="clause.valueScore"
              />
              <a-icon-font
                class="add-recommend-clause"
                type="iconzengjia"
                @click="addRecommendClause(clause)"
              />
            </div>
          </template>
        </div>
      </div>
    </div>

    <!--  footer  -->
    <div class="footer-buttons">
      <div class="btn import-btn" @click="confirm">
        确定
      </div>
      <div class="btn cancel-btn" @click="cancelChange">取消</div>
    </div>
  </div>
</template>

<script lang="ts">
/**
 * Auto Join
 */
import { Watch, Vue, Component } from 'vue-property-decorator'
import DataViewStore from '@/store/modules/dataview'
import { cloneDeep } from 'lodash'
// 韦恩图
import VennOfJoinType from '@/components/studio/data/set-params/auto-join/VennOfJoinType.vue'
// 查看详情
import PopoverDetail from '@/components/studio/data/set-params/auto-join/PopoverDetail.vue'
// 推荐的 子句 bar
import PopoverCoefficientBar from '@/components/studio/data/set-params/auto-join/PopoverCoefficientBar.vue'
// 结果概览
import ResultOverview from '@/components/studio/data/set-params/auto-join/ResultOverview.vue'

import {
  OperatorGroupIconBackGround,
  DataIcon,
} from '@/components/studio/data/graph-compoments/node-icon-util'
import { apiJoinRecommend, queryJoinResult } from '@/api/task'
// interface
import {
  OverviewResult,
  RecommendClause,
  JoinClause,
} from '@/components/studio/data/set-params/auto-join/interface-auto-join'

@Component({
  components: {
    VennOfJoinType,
    PopoverDetail,
    PopoverCoefficientBar,
    ResultOverview,
  },
})
export default class EtlJoin extends Vue {
  public joinType: number = 3 // join 类型
  public autoJoinRecommendation: RecommendClause[] = [] // 推荐子句列表  从 节点 data json 中取
  public result: OverviewResult | null = null // 结果概览
  private resultLoading: boolean = false // 结果概览 loading 状态
  private isSample: boolean = false
  private showResultOverview: boolean = false // 是否显示 结果概览
  private resultWarning: string = ''
  public joinClauseList: JoinClause[] = [] // 已应用的联接子句

  private leftRecommendColumnSortByRight: string[] = [] // 编辑联接子句时根据右表已选列给出左表排序后的候选列
  private rightRecommendColumnSortByLeft: string[] = [] // 编辑联接子句时根据左表已选列给出右表排序后的候选列

  // 全量任务状态
  private get executionCompletionType(): boolean {
    return DataViewStore.executionCompletionType
  }

  // 当前节点的 id
  private get selectNode() {
    return DataViewStore.selectNode
  }

  public get leftColumns() {
    if (this.leftRecommendColumnSortByRight.length > 0) {
      return this.leftRecommendColumnSortByRight
    }
    return this.selectNode.data.input[0].tableCols
  }
  public get rightColumns() {
    if (this.rightRecommendColumnSortByLeft.length > 0) {
      return this.rightRecommendColumnSortByLeft
    }
    return this.selectNode.data.input[1].tableCols
  }
  // 左节点颜色
  public get leftColor() {
    if (typeof this.selectNode.data.input[0]?.subType === 'number') {
      return OperatorGroupIconBackGround[this.selectNode.data.input[0]?.subType]
        .color
    }
    // 否则就是数据节点
    return DataIcon.color
  }
  // 右节点颜色
  public get rightColor() {
    if (typeof this.selectNode.data.input[1]?.subType === 'number') {
      return OperatorGroupIconBackGround[this.selectNode.data.input[1]?.subType]
        .color
    }
    return DataIcon.color
  }
  // 已使用 推荐联接子句的 ids
  public get clauseIds() {
    return this.joinClauseList.map((clause: any) => clause.id)
  }
  // 联接子句推荐的联接子句是否展示（已使用的推荐 不展示）
  public isShow(id: number) {
    return !this.clauseIds.includes(id)
  }

  public created() {
    this.initSet(this.selectNode) // 回显
  }

  // 监听激活的节点
  @Watch('selectNode', { deep: true })
  private changeSelectNode(selectNode: any) {
    if (selectNode) {
      this.initSet(selectNode)
    }
  }

  // 初始化  参数复现
  public async initSet(selectNode: any) {
    if (this.selectNode.data.conditions) {
      this.joinClauseList = cloneDeep(this.selectNode.data.conditions) // join claus
    }
    this.joinType = selectNode.data.mod // join 类型
    this.autoJoinRecommendation = cloneDeep(
      this.selectNode.data.autoJoinRecommendation
    ) // 推荐的子句 list
  }

  // 链接子句的 关系修改 > < = !=
  public relationValueChange(index: number) {
    this.joinClauseList[index].id = null
    // this.isSample = true  // 关闭采样
  }

  /**
   * 修改 子句 left  子句关系  子句 right
   */
  public valueChange(index: number, type: string, column: any) {
    this.joinClauseList[index].id = null
    this.queryJoinRecommend(type, column)
    // this.isSample = true  // 关闭采样
  }

  /**
   * 根据操作项，获取对侧的匹配排序
   */
  public async queryJoinRecommend(type: string, column: string) {
    const parameters = {
      taskId: this.selectNode.id,
      side: type,
      col: column,
    }
    const response = await apiJoinRecommend({ data: parameters })
    const { code, result } = response.data
    if (code === 100) {
      if (type === 'left') {
        this.rightRecommendColumnSortByLeft = result
      } else {
        this.leftRecommendColumnSortByRight = result
      }
    }
  }

  /**
   * 列选项搜索功能
   */
  public filterOption(input: any, option: any) {
    return option.componentOptions.children[0].text
      .toLowerCase()
      .includes(input.toLowerCase())
  }

  /**
   * 手动添加空状态联接子句
   */
  private addClause() {
    const clauseTemplate: any = {
      leftHeaderName: '',
      operator: '=',
      rightHeaderName: '',
      id: null,
      headerScore: 0,
      score: 0,
      valueScore: 0,
      leftTableName: '',
      rightTableName: '',
    }
    this.joinClauseList.push(clauseTemplate)
  }
  // 移除指定联接子句项目
  private removeClause(index: number) {
    this.joinClauseList.splice(index, 1)
  }
  // emit 联接类型的设置
  public toggleJoin(joinType: number) {
    this.joinType = joinType
  }

  // 深度监听联接子句
  @Watch('joinClauseList', { deep: true })
  public joinClauseListUpdate() {
    this.queryJoinResult()
  }

  /**
   * 请求 join 结果概览
   */
  public async queryJoinResult() {
    // 先检查联接子句合法性
    const parametersLegal = this.checkClauseValid(this.joinClauseList)
    // 子句合法更新结果预览
    if (parametersLegal) {
      this.resultLoading = true // 加载中
      const parameters = {
        id: DataViewStore.selectNode.id,
        projectId: DataViewStore.selectNode.projectId,
        pipelineId: DataViewStore.selectNode.pipelineId,
        data: {
          conditions: this.joinClauseList,
          isSample: this.isSample,
        },
      }
      await queryJoinResult({ data: parameters })
        .then((response: any) => {
          if (response.data.code === 100) {
            this.result = response.data.result
            this.showResultOverview = true
          } else if (response.data.code === 500) {
            this.$message.warning(response.data.tips)
            this.showResultOverview = false // 不显示概览
          }
        })
        .finally(() => {
          this.resultLoading = false
        })
        .catch((error: any) => {
          this.showResultOverview = false // 不显示概览
          this.resultWarning = '-- 获取结果概览失败 --' // 请求失败 （超时）
          console.log(error)
        })
      // this.isSample = false  // 关闭采样
    } else {
      // this.$message.warn('请添加联接子句 / 将联接子句补充完整 ！')
      this.resultLoading = false
      this.resultWarning = '-- 请添加联接子句 / 检查联接子句完整性 --'
      if (this.joinClauseList.length === 0) {
        this.showResultOverview = false
        this.result = null
      }
    }
  }

  /**
   * 应用推荐联接子句
   */
  public addRecommendClause(clause: RecommendClause) {
    const clauseTemplate: any = {
      leftHeaderName: clause.leftHeaderName,
      operator: '=',
      rightHeaderName: clause.rightHeaderName,
      id: clause.id,
      headerScore: clause.headerScore,
      score: clause.score,
      valueScore: clause.valueScore,
      leftTableName: clause.leftTableName,
      rightTableName: clause.rightTableName,
    }
    this.joinClauseList.push(clauseTemplate)
    // this.isSample = true  // 关闭采样
  }

  /**
   * 验证子句的合法
   */
  public checkClauseValid(joinClauseList: any) {
    let parametersLegal = true
    if (joinClauseList.length === 0) {
      parametersLegal = false
    } else {
      joinClauseList.forEach((clause: JoinClause) => {
        if (!clause.leftHeaderName || !clause.rightHeaderName) {
          parametersLegal = false
        }
      })
    }
    return parametersLegal
  }

  public confirm() {
    if (this.joinType === 8) {
      this.$message.warn('联接类型无意义，请修改！')
      return
    }
    const parametersLegal = this.checkClauseValid(this.joinClauseList)
    if (parametersLegal) {
      this.$emit('confirm', {
        mod: this.joinType,
        conditions: this.joinClauseList,
      })
    } else {
      this.$message.warn('请添加联接子句 / 将联接子句补充完整 ！')
    }
  }

  /**
   * 取消修改
   */
  public cancelChange() {
    this.initSet(this.selectNode)
  }
}
</script>

<style lang="less" scoped>
@import '@/components/studio/data/set-params/setParams';

/* 左右表名 header */
.table-name-header {
  cursor: pointer;
  display: flex;
  justify-content: flex-start;
  margin-bottom: 12px;
  width: 100%;

  .auto-join-name {
    text-align: left;
    width: 50px;
  }

  .table-name {
    max-width: calc(50% - 45px);
    padding-left: 20px;
    text-align: left;
  }
}

// 连接字句
.join-clause {
  width: 100%;

  // 联接子句内容
  .clause-content {
    align-items: center;
    display: flex;
    height: 32px;
    justify-content: space-between;
    margin: 3px 0;
    width: 100%;

    .clause-left {
      align-items: center;
      cursor: pointer;
      display: flex;
      height: 32px;
      justify-content: space-between;
      line-height: 30px;
      padding: 0 3px;
      width: 332px;

      // 左右表字段
      .clause-conditions {
        display: inline-block;
        width: 120px;
      }

      // 关系
      .clause-symbol {
        display: inline-block;
        width: 70px;
      }
    }

    .delete-clause-icon {
      //opacity: 0;
      cursor: pointer;
    }

    .popover-detail {
      cursor: pointer;
      //opacity: 0;
    }

    &:hover {
      background-color: #eaeaea;

      .delete-clause-icon {
        opacity: 1;
      }

      .popover-detail {
        opacity: 1;
      }
    }
  }

  // 手动添加联接子句
  .add-clause {
    align-items: center;
    color: #5760e6;
    display: flex;
    height: 24px;
    justify-content: center;

    span {
      cursor: pointer;
    }
  }

  // 联接子句为空
  .empty-join-clause {
    background-color: #eaeaea;
    color: #9b9da8;
    font-size: 14px;
    height: 32px;
    line-height: 32px;
    margin: 3px 0;
    text-align: center;
  }
}
// 连接类型
.auto-join-model {
  align-items: center;
  display: flex;
  justify-content: center;
  width: 100%;

  .auto-join-model {
    margin: 0 12px;
  }

  .join-node-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 115px;
  }
}

// 各组成模块的 title 联接子句， 联接烈性 结果概览 推荐联接子句
.module-title {
  color: #5d637e;
  display: flex;
  font-size: 12px;
  font-weight: 600;
  height: 17px;
  letter-spacing: 1px;
  line-height: 17px;
  margin-bottom: 6px;

  .title-text {
    color: #9b9da8;
    font-size: 12px;
    font-weight: 500;
  }
}

// 添加 删除按钮
.delete-clause-icon {
  cursor: pointer;
  font-size: 16px;
  margin: 0 4px;
}

.results-overview-content {
  height: 96px;
  margin-bottom: 12px;

  .empty-clause-result {
    align-items: center;
    color: #9b9da8;
    display: flex;
    height: 96px;
    justify-content: center;
    width: 100%;
  }
}

// 推荐的联接子句
.auto-join-recommend {
  overflow: hidden;
  width: 100%;

  // 推荐的 bar 图例
  .legend-color {
    display: flex;
    justify-content: center;

    .header-score-legend {
      margin: 0 8px 0 18px;
      position: relative;

      &::before {
        background-color: #8289dd;
        content: '';
        height: 8px;
        left: -14px;
        position: absolute;
        top: 4px;
        width: 10px;
      }
    }

    .value-score-legend {
      margin: 0 8px 0 18px;
      position: relative;

      &::before {
        background-color: #ced0ed;
        content: '';
        height: 8px;
        left: -14px;
        position: absolute;
        top: 4px;
        width: 10px;
      }
    }
  }

  // 推荐的子句
  .recommend-clause {
    width: 100%;

    .clause-item {
      align-items: center;
      cursor: pointer;
      display: flex;
      height: 22px;
      justify-content: space-between;
      margin: 2px 0;

      /* 连接关系 */
      .clause-text {
        display: flex;
        justify-content: space-between;
        width: 150px;

        .clause-field {
          overflow: hidden;
          text-align: right;
          text-overflow: ellipsis;
          white-space: nowrap;
          width: 40%;
        }

        .clause-field-right {
          text-align: left;
        }

        .relation {
          color: #5d637e;
          text-align: center;
          width: 20%;
        }
      }

      /* 添加 icon */
      .add-recommend-clause {
        font-size: 16px;
        margin-left: 6px;
        opacity: 0;
      }

      &:hover {
        background-color: #eaeaea;

        .add-recommend-clause {
          opacity: 1;
        }
      }
    }
  }

  .recommend-coefficient {
    z-index: 10;
  }
}
</style>
